﻿using Engine;
using Engine.Graphics;
using Engine.Input;
using Engine.Media;
using Game.NetWork;
using Game.NetWork.Packages;
using GameEntitySystem;
using System.Collections.Generic;
using System;
using Test1;


namespace Game
{
    public class FCModLoaderShengcheng : ModLoader
    {
        public class CavePoint
        {
            public Vector3 Position;

            public Vector3 Direction;

            public int BrushType;

            public int Length;

            public int StepsTaken;
        }

        public struct NumberWeightPair
        {
            public int number;

            public int weight;

            public NumberWeightPair(int number, int weight)
            {
                this.number = number;
                this.weight = weight;
            }
        }

        public class RoadPoint
        {
            public Point3 Position;

            public int BrushType;

            public bool TG;

            public bool TFirst;

            public bool Tturn;

            public bool is_Vice;

            public Point2 chunkCoords;
        }

        public class BuildPoint
        {
            public Point3 Position;

            public int BrushType;

            public bool TG;
        }

        public ComponentTest1 m_componentTest1;

        public ComponentPlayer m_componentPlayer;

        public SubsystemGameInfo m_subsystemGameInfo;

        public bool TGExtras;

        public int m_seed;

        public SubsystemTerrain m_subsystemTerrain;

        public Vector2 m_temperatureOffset;

        public Vector2 m_humidityOffset;

        public float TGBiomeScaling;

        public WorldSettings m_worldSettings;

        public SubsystemParticles m_subsystemParticles;

        public bool TGCavesAndPockets;

        public TerrainSerializer23 m_terrainSerializer23;

        public SubsystemPickables m_subsystemPickables;

        public SubsystemSky m_subsystemSky;

        public SubsystemBodies m_subsystemBodies;

        public SubsystemPlayers m_subsystemPlayers;

        public float TGOceanSlopeVariation;

        public float TGOceanSlope;

        public Vector2 m_mountainsOffset;

        public Vector2 m_riversOffset;

        public float TGIslandsFrequency;

        public float TGHillsPercentage;

        public float TGHillsStrength;

        public float TGMountainsStrength;

        public float TGMountainRangeFreq;

        public float TGMountainsPercentage;

        public int TGHillsOctaves;

        public float TGHillsFrequency;

        public float TGHillsPersistence;

        public float TGHeightBias;

        public float TGRiversStrength;

        public Vector2? m_islandSize;

        public Vector2 m_oceanCorner;

        public float TGShoreFluctuations;

        public float TGShoreFluctuationsScaling;

        public float TGTurbulenceStrength;

        public float TGTurbulenceFreq;

        public int TGTurbulenceOctaves;

        public float TGTurbulencePersistence;

        public float TGMinTurbulence;

        public float TGTurbulenceZero;

        public float TGDensityBias;

        public static List<TerrainBrush> m_fcmagmaPocketBrushes;

        public static List<TerrainBrush> m_fcmagmaPocketBrushes2;

        public static List<TerrainBrush> m_fcMoonPocketBrushes;

        public static List<List<TerrainBrush>> m_fccaveBrushesByType;

        public static List<RoadPoint> listRD;

        public static List<BuildPoint> listBD;

        public static List<RoadPoint> listRDF;

        public static Dictionary<Point2, int> Dic_Chunk_Village3;

        public static Dictionary<Point2, TerrainChunk> Dic_Chunk_Village_Build;

        public int StepsTaken;

        public int StepsTaken_Max;

        public bool IsNightVisionActive { get; set; }

        public static int GetItemCountInInventory(int value, IInventory inventory)
        {
            int num = 0;
            for (int i = 0; i < inventory.SlotsCount; i++)
            {
                if (inventory.GetSlotValue(i) == value)
                {
                    num += inventory.GetSlotCount(i);
                }
            }

            return num;
        }

        public static void AddItem(ComponentMiner componentMiner, SubsystemPickables subsystemPickables, int value, int count)
        {
            IInventory inventory = componentMiner.Inventory;
            for (int i = 0; i < count; i++)
            {
                if (ComponentInventoryBase.FindAcquireSlotForItem(inventory, value) >= 0)
                {
                    ComponentInventoryBase.AcquireItems(inventory, value, 1);
                }
                else
                {
                    subsystemPickables.AddPickable(value, 1, componentMiner.ComponentCreature.ComponentBody.Position + new Vector3(0f, 1f, 0f), null, null);
                }
            }
        }

        public static void RemoveItemFromInventory(int value, int count, IInventory inventory)
        {
            for (int i = 0; i < inventory.SlotsCount; i++)
            {
                if (count <= 0)
                {
                    break;
                }

                if (inventory.GetSlotValue(i) == value)
                {
                    int num = MathUtils.Min(count, inventory.GetSlotCount(i));
                    count -= num;
                    inventory.RemoveSlotItems(i, num);
                }
            }
        }

        public override void __ModInitialize()
        {
            ModsManager.RegisterHook("OnTerrainContentsGenerated", this);
            ModsManager.RegisterHook("AttackBody", this);
            ModsManager.RegisterHook("InitializeCreatureTypes", this);
            ModsManager.RegisterHook("ToFreeChunks", this);
            ModsManager.RegisterHook("ToAllocateChunks", this);
            ModsManager.RegisterHook("CalculateLighting", this);
            ModsManager.RegisterHook("OnCreatureInjure", this);
            ModsManager.RegisterHook("SetRainAndSnowColor", this);
            ModsManager.RegisterHook("OnModelRendererDrawExtra", this);
            ModsManager.RegisterHook("OnLoadingStart", this);
            ModsManager.RegisterHook("BlocksInitalized", this);
            ModsManager.RegisterHook("UpdateInput", this);
            SubsystemNaturallyBuildings.Initialize();
        }

        public override void OnLoadingStart(List<Action> actions)
        {
            base.OnLoadingStart(actions);
            actions.Add(delegate
            {
                PackageManager.RegisterPackage(new ComponentGaoluPackage());
                PackageManager.RegisterPackage(new FCBlockEditPackage());
                PackageManager.RegisterPackage(new ComponentLianyaoPackage());
                PackageManager.RegisterPackage(new ComponentFajiaoPackage());
                PackageManager.RegisterPackage(new ComponentMicroPackage());
                PackageManager.RegisterPackage(new ComponentXiaoshiPackage());
                PackageManager.RegisterPackage(new ComponentHealPackage());
                PackageManager.RegisterPackage(new ComponentATKPackage());
                PackageManager.RegisterPackage(new ComponentSpeedPackage());
                PackageManager.RegisterPackage(new ComponentTest1Package());
                PackageManager.RegisterPackage(new ComponentCoffer2Package());
                PackageManager.RegisterPackage(new ComponentMFEnginePackage());
                PackageManager.RegisterPackage(new ComponentTaskPackage());
                PackageManager.RegisterPackage(new SubsystemNPCPackage());
                Log.Information("加载数据包");
                Log.Information("加载数据包ceshi");
            });
        }

        public override void BlocksInitalized()
        {
            GunTestManager.Initialize();
        }

        public override void UpdateInput(ComponentInput componentInput, WidgetInput widgetInput)
        {
            componentInput.m_playerInput.ToggleCreativeFly = false;
            ComponentNewFirstPersonModel componentNewFirstPersonModel = componentInput.Entity.FindComponent<ComponentNewFirstPersonModel>();
            if (componentNewFirstPersonModel != null)
            {
                componentNewFirstPersonModel.IsFClicked = widgetInput.IsKeyDownOnce(Key.F);
            }
        }

        public override bool SetRainAndSnowColor(ref Color rainColor, ref Color snowColor)
        {
            return false;
        }

        public override void OnModelRendererDrawExtra(SubsystemModelsRenderer modelsRenderer, ComponentModel componentModel, Camera camera, float? alphaThreshold)
        {
            ComponentBody componentBody = componentModel.Entity.FindComponent<ComponentBody>();
            if (componentBody == null || componentModel == null || componentBody.ParentBody != null)
            {
                return;
            }

            ComponentCreature componentCreature = componentModel.Entity.FindComponent<ComponentCreature>();
            ComponentHealth componentHealth = componentModel.Entity.FindComponent<ComponentHealth>();
            if (componentHealth != null)
            {
                Vector3 vector = Vector3.Transform(componentCreature.ComponentBody.Position + 1.2f * Vector3.UnitY * componentCreature.ComponentBody.BoxSize.Y, camera.ViewMatrix);
                if (vector.Z < 0f && Color.Lerp(Color.White, Color.Transparent, MathUtils.Saturate((vector.Length() - 4f) / 3f)).A > 8)
                {
                    float num = 15f;
                    Color color = Color.White * new Color(num, num, num, 255f);
                    Color color2 = new Color(1f - componentHealth.Health, componentHealth.Health, 0f) * new Color(num, num, num);
                    Vector3 vector2 = vector + Vector3.UnitY * 0.3f;
                    Vector3 right = Vector3.TransformNormal(0.005f * Vector3.Normalize(Vector3.Cross(camera.ViewDirection, Vector3.UnitY)), camera.ViewMatrix);
                    Vector3 down = Vector3.TransformNormal(-0.005f * Vector3.UnitY, camera.ViewMatrix);
                    BitmapFont bitmapFont = LabelWidget.BitmapFont;
                    FontBatch3D fontBatch3D = modelsRenderer.PrimitivesRenderer.FontBatch(bitmapFont, 1, DepthStencilState.DepthRead, RasterizerState.CullNoneScissor, BlendState.AlphaBlend, SamplerState.LinearClamp);
                    FlatBatch3D flatBatch3D = modelsRenderer.PrimitivesRenderer.FlatBatch(1, DepthStencilState.DepthRead, RasterizerState.CullNoneScissor, BlendState.AlphaBlend);
                    Vector3 vector3 = vector2 + new Vector3(-0.51f, 0.01f, 0f);
                    Vector3 vector4 = vector2 + new Vector3(0.51f, 0.01f, 0f);
                    Vector3 vector5 = vector2 + new Vector3(0.51f, -0.13f, 0f);
                    Vector3 vector6 = vector2 + new Vector3(-0.51f, -0.13f, 0f);
                    Vector3 p = vector2 + new Vector3(-0.5f, 0f, 0f);
                    Vector3 p2 = vector2 + new Vector3(-0.5f + componentHealth.Health, 0f, 0f);
                    Vector3 p3 = vector2 + new Vector3(-0.5f + componentHealth.Health, -0.12f, 0f);
                    Vector3 p4 = vector2 + new Vector3(-0.5f, -0.12f, 0f);
                    flatBatch3D.QueueLine(vector3, vector4, color);
                    flatBatch3D.QueueLine(vector4, vector5, color);
                    flatBatch3D.QueueLine(vector5, vector6, color);
                    flatBatch3D.QueueLine(vector6, vector3, color);
                    Vector3 position = vector2 + Vector3.UnitY * 0.3f;
                    string text = $"生命:{(int)(componentHealth.Health * componentHealth.AttackResilience)}/{(int)componentHealth.AttackResilience}";
                    fontBatch3D.QueueText(componentCreature.DisplayName, position, right, down, color, TextAnchor.HorizontalCenter);
                    fontBatch3D.QueueText(text, position, right, down, Color.LightRed, TextAnchor.HorizontalCenter | TextAnchor.Bottom);
                    flatBatch3D.QueueQuad(p, p2, p3, p4, color2);
                }
            }
        }

        public override void OnCreatureInjure(ComponentHealth componentHealth, float amount, ComponentCreature attacker, bool ignoreInvulnerability, string cause, out bool Skip)
        {
            Skip = false;
            ComponentPlayer componentPlayer = componentHealth.Entity.FindComponent<ComponentPlayer>();
            if (attacker != null)
            {
                if (attacker.DisplayName == "失魂游尸")
                {
                    if (componentPlayer != null)
                    {
                        if (componentHealth.Health > 0.2f)
                        {
                            componentHealth.Health -= 0.2f;
                        }
                        else
                        {
                            componentHealth.Health = 0f;
                        }

                        if (CommonLib.WorkType != WorkType.Client)
                        {
                            CommonLib.Net.QueuePackage(new ComponentHealthPackage(componentHealth));
                        }

                        Skip = true;
                        return;
                    }

                    Skip = false;
                }
                else if (attacker != null)
                {
                    if (componentPlayer != null)
                    {
                        BuffManager buffManager = new BuffManager(componentPlayer);
                        if (attacker.DisplayName == "尸鬼")
                        {
                            buffManager.AddBuff(4, 2f, 0.6f);
                        }

                        ComponentTest1 componentTest = componentPlayer.Entity.FindComponent<ComponentTest1>();
                        float num = componentTest.m_mp * componentTest.MaxMagicPower;
                        if (MathUtils.Floor(componentPlayer.PlayerData.Level) > 7f)
                        {
                            if (num > 0f && num >= amount * componentHealth.AttackResilience)
                            {
                                componentTest.m_mp -= 1f / componentTest.MaxMagicPower * amount * componentHealth.AttackResilience;
                                if (CommonLib.WorkType != WorkType.Client)
                                {
                                    CommonLib.Net.QueuePackage(new ComponentTest1Package(componentTest, ComponentTest1Package.EventType.SyncMagic, 1));
                                }

                                Skip = true;
                            }
                            else if (num > 0f && num < amount * componentHealth.AttackResilience)
                            {
                                ComponentClothing componentClothing = componentPlayer.ComponentClothing;
                                SubsystemTerrain subsystemTerrain = componentClothing.m_subsystemTerrain;
                                ComponentBody componentBody = componentPlayer.ComponentBody;
                                SubsystemParticles subsystemParticles = componentClothing.m_subsystemParticles;
                                ComponentMiner componentMiner = componentPlayer.ComponentMiner;
                                SubsystemSoundMaterials subsystemSoundMaterials = componentMiner.m_subsystemSoundMaterials;
                                subsystemSoundMaterials.PlayImpactSound(15, componentBody.Position, 5f);
                                componentPlayer.ComponentGui.DisplaySmallMessage("灵能护盾破碎！灵能彻底耗尽！请立刻返回安全的地方！", Color.LightYellow, blinking: true, playNotificationSound: true);
                                componentTest.m_mp = 0f;
                                if (componentHealth.Health > 0.1f)
                                {
                                    componentHealth.Health -= 0.1f;
                                }
                                else
                                {
                                    componentHealth.Health = 0f;
                                }

                                if (CommonLib.WorkType != WorkType.Client)
                                {
                                    CommonLib.Net.QueuePackage(new ComponentTest1Package(componentTest, ComponentTest1Package.EventType.SyncMagic, 1));
                                    CommonLib.Net.QueuePackage(new ComponentHealthPackage(componentHealth));
                                }

                                Skip = true;
                            }
                            else if (num <= 0f)
                            {
                                Skip = false;
                            }
                        }
                    }
                }
                else
                {
                    Skip = false;
                }
            }
            else if (amount != 0f)
            {
                if (componentPlayer != null)
                {
                    ComponentTest1 componentTest2 = componentPlayer.Entity.FindComponent<ComponentTest1>();
                    float num2 = componentTest2.m_mp * componentTest2.MaxMagicPower;
                    if (MathUtils.Floor(componentPlayer.PlayerData.Level) > 7f)
                    {
                        if (num2 > 0f && num2 >= amount * componentHealth.AttackResilience)
                        {
                            componentTest2.m_mp -= 1f / componentTest2.MaxMagicPower * amount * componentHealth.AttackResilience;
                            if (CommonLib.WorkType != WorkType.Client)
                            {
                                CommonLib.Net.QueuePackage(new ComponentTest1Package(componentTest2, ComponentTest1Package.EventType.SyncMagic, 1));
                            }

                            Skip = true;
                        }
                        else if (num2 > 0f && num2 < amount * componentHealth.AttackResilience)
                        {
                            ComponentClothing componentClothing2 = componentPlayer.ComponentClothing;
                            SubsystemTerrain subsystemTerrain2 = componentClothing2.m_subsystemTerrain;
                            ComponentBody componentBody2 = componentPlayer.ComponentBody;
                            ComponentMiner componentMiner2 = componentPlayer.ComponentMiner;
                            SubsystemSoundMaterials subsystemSoundMaterials2 = componentMiner2.m_subsystemSoundMaterials;
                            subsystemSoundMaterials2.PlayImpactSound(15, componentBody2.Position, 5f);
                            componentTest2.m_mp = 0f;
                            componentPlayer.ComponentGui.DisplaySmallMessage("灵能护盾破碎！灵能彻底耗尽！请立刻返回安全的地方！", Color.LightYellow, blinking: true, playNotificationSound: true);
                            if (componentHealth.Health > 0.1f)
                            {
                                componentHealth.Health -= 0.1f;
                            }
                            else
                            {
                                componentHealth.Health = 0f;
                            }

                            if (CommonLib.WorkType != WorkType.Client)
                            {
                                CommonLib.Net.QueuePackage(new ComponentTest1Package(componentTest2, ComponentTest1Package.EventType.SyncMagic, 1));
                                CommonLib.Net.QueuePackage(new ComponentHealthPackage(componentHealth));
                            }

                            Skip = true;
                        }
                        else if (num2 <= 0f)
                        {
                            Skip = false;
                        }
                    }
                }
            }
            else
            {
                Skip = false;
            }

            Entity entity = componentHealth.Entity;
            if (entity == null)
            {
                return;
            }

            string name = entity.ValuesDictionary.DatabaseObject.Name;
            if (name == "BSLord")
            {
                Skip = true;
            }

            if (name == "DoDo")
            {
                Skip = true;
            }

            if (name == "YS")
            {
                string text = LanguageControl.Get(ComponentHealth.fName, 1);
                string text2 = LanguageControl.Get(ComponentHealth.fName, 2);
                string text3 = LanguageControl.Get(ComponentHealth.fName, 5);
                string text4 = LanguageControl.Get(ComponentHealth.fName, 7);
                string text5 = LanguageControl.Get("SubsystemSpikesBlockBehavior", 0);
                string text6 = "Crushed";
                if (cause == text || cause == text2 || cause == text3 || cause == text4 || cause == text5 || cause == text6)
                {
                    Skip = true;
                }
            }
        }

        public override void InitializeCreatureTypes(SubsystemCreatureSpawn spawn, List<SubsystemCreatureSpawn.CreatureType> creatureTypes)
        {
        }

        public void 生成西瓜(TerrainChunk chunk)
        {
            int x = chunk.Coords.X;
            int y = chunk.Coords.Y;
            Random random = new Random(m_seed + x + 1495 * y);
            if (random.Bool(0.2f))
            {
                return;
            }

            int num = random.Int(0, MathUtils.Max(1, 1));
            for (int i = 0; i < num; i++)
            {
                int num2 = random.Int(1, 14);
                int num3 = random.Int(1, 14);
                int humidityFast = chunk.GetHumidityFast(num2, num3);
                int temperatureFast = chunk.GetTemperatureFast(num2, num3);
                if (humidityFast < 10 || temperatureFast <= 6)
                {
                    continue;
                }

                for (int j = 0; j < 5; j++)
                {
                    int x2 = num2 + random.Int(-1, 1);
                    int z = num3 + random.Int(-1, 1);
                    for (int num4 = 254; num4 >= 0; num4--)
                    {
                        switch (Terrain.ExtractContents(chunk.GetCellValueFast(x2, num4, z)))
                        {
                            case 8:
                                chunk.SetCellValueFast(x2, num4 + 1, z, random.Bool(0.25f) ? Terrain.MakeBlockValue(936) : Terrain.MakeBlockValue(938));
                                break;
                            case 0:
                                continue;
                        }

                        break;
                    }
                }
            }
        }

        public void FCGenerateGrassAndPlants(TerrainChunk chunk)
        {
            if (!TGExtras)
            {
                return;
            }

            Random random = new Random(m_seed + chunk.Coords.X + 3900 * chunk.Coords.Y);
            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    for (int num = 254; num >= 0; num--)
                    {
                        int cellValueFast = chunk.GetCellValueFast(i, num, j);
                        int num2 = Terrain.ExtractContents(cellValueFast);
                        if (num2 != 0)
                        {
                            if (!(BlocksManager.Blocks[num2] is FluidBlock))
                            {
                                int temperatureFast = chunk.GetTemperatureFast(i, j);
                                int humidityFast = chunk.GetHumidityFast(i, j);
                                int num3 = FCGenerateRandomPlantValue(random, cellValueFast, temperatureFast, humidityFast, num + 1);
                                if (num3 != 0)
                                {
                                    chunk.SetCellValueFast(i, num + 1, j, num3);
                                }
                            }

                            break;
                        }
                    }
                }
            }
        }

        public int FCGenerateRandomPlantValue(Random random, int groundValue, int temperature, int humidity, int y)
        {
            int num = Terrain.ExtractContents(groundValue);
            switch (num)
            {
                default:
                    return 0;
                case 7:
                    if (humidity >= 8 || random.Float(0f, 1f) >= 0.01f)
                    {
                        return 0;
                    }

                    if (random.Float(0f, 1f) < 0.05f)
                    {
                        return Terrain.MakeBlockValue(99, 0, 0);
                    }

                    return Terrain.MakeBlockValue(28, 0, 0);
                case 2:
                case 3:
                case 5:
                case 8:
                case 62:
                case 66:
                case 67:
                    if (humidity >= 6)
                    {
                        if (!SubsystemWeather.IsPlaceFrozen(temperature, y) && temperature > 6)
                        {
                            if (random.Float(0f, 1f) < (float)humidity / 60f)
                            {
                                int result = Terrain.MakeBlockValue(19, 0, TallGrassBlock.SetIsSmall(0, isSmall: false));
                                if (num == 2 || num == 8)
                                {
                                    float num2 = random.Float(0f, 1f);
                                    if (num2 < 0.04f)
                                    {
                                        result = Terrain.MakeBlockValue(937);
                                    }
                                    else if (!(num2 < 0.075f))
                                    {
                                    }
                                }

                                return result;
                            }

                            if (random.Float(0f, 1f) < (float)humidity / 60f && humidity >= 10)
                            {
                                int result2 = Terrain.MakeBlockValue(0, 0, 0);
                                float num3 = random.Float(0f, 1f);
                                if (num3 < 0.05f)
                                {
                                    int[] array = new int[12]
                                    {
                                    5, 9, 10, 11, 13, 14, 15, 16, 27, 31,
                                    32, 33
                                    };
                                    int num4 = random.Int(0, 11);
                                    result2 = Terrain.MakeBlockValue(986, 0, array[num4]);
                                }

                                return result2;
                            }
                        }
                        else if (temperature <= 2 && random.Float(0f, 1f) < (float)humidity / 16f)
                        {
                            int result3 = Terrain.MakeBlockValue(0, 0, TallGrassBlock.SetIsSmall(0, isSmall: false));
                            float num5 = random.Float(0f, 1f);
                            if (num5 < 0.1f)
                            {
                                int[] array2 = new int[4] { 0, 3, 20, 21 };
                                int num6 = random.Int(0, 3);
                                result3 = Terrain.MakeBlockValue(986, 0, array2[num6]);
                            }

                            return result3;
                        }
                    }

                    return 0;
            }
        }

        public void 生成向日葵(TerrainChunk chunk)
        {
            if (!TGExtras)
            {
                return;
            }

            Random random = new Random(m_seed + chunk.Coords.X + 3943 * chunk.Coords.Y);
            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    for (int num = 254; num >= 0; num--)
                    {
                        int cellValueFast = chunk.GetCellValueFast(i, num, j);
                        int num2 = Terrain.ExtractContents(cellValueFast);
                        if (num2 != 0)
                        {
                            if (!(BlocksManager.Blocks[num2] is FluidBlock))
                            {
                                int temperatureFast = chunk.GetTemperatureFast(i, j);
                                int humidityFast = chunk.GetHumidityFast(i, j);
                                int num3 = FCPlantManager.GenerateRandomPlantValue(random, cellValueFast, temperatureFast, humidityFast, num + 1);
                                if (num3 != 0)
                                {
                                    chunk.SetCellValueFast(i, num + 1, j, num3);
                                }

                                if (num2 == 2)
                                {
                                    chunk.SetCellValueFast(i, num, j, Terrain.MakeBlockValue(8, 0, 0));
                                }
                            }

                            break;
                        }
                    }
                }
            }
        }

        public void generateMineralLikeCoal(TerrainChunk chunk, int value, int replacevalue, int minHeight, int maxHeight)
        {
            int x = chunk.Coords.X;
            int y = chunk.Coords.Y;
            List<TerrainBrush> list = new List<TerrainBrush>();
            Random random = new Random(17);
            for (int i = 0; i < 16; i++)
            {
                TerrainBrush terrainBrush = new TerrainBrush();
                int num = random.Int(3, 15);
                for (int j = 0; j < num; j++)
                {
                    Vector3 vector = 0.5f * Vector3.Normalize(new Vector3(random.Float(-1f, 1f), random.Float(-1f, 1f), random.Float(-1f, 1f)));
                    int num2 = random.Int(3, 10);
                    Vector3 zero = Vector3.Zero;
                    for (int k = 0; k < num2; k++)
                    {
                        terrainBrush.AddBox((int)MathUtils.Floor(zero.X), (int)MathUtils.Floor(zero.Y), (int)MathUtils.Floor(zero.Z), 1, 1, 1, value);
                        zero += vector;
                    }
                }

                if (i == 0)
                {
                    terrainBrush.AddCell(0, 0, 0, 934);
                }

                terrainBrush.Compile();
                list.Add(terrainBrush);
            }

            for (int l = x - 1; l <= x + 1; l++)
            {
                for (int m = y - 1; m <= y + 1; m++)
                {
                    float num3 = CalculateMountainRangeFactor(l * 16, m * 16);
                    int num4 = (int)(5f + 2f * num3 * SimplexNoise.OctavedNoise(l, m, 0.33f, 1, 1f, 1f));
                    for (int n = 0; n < num4; n++)
                    {
                        int x2 = l * 16 + random.Int(0, 15);
                        int y2 = random.Int(minHeight, maxHeight);
                        int z = m * 16 + random.Int(0, 15);
                        list[random.Int(0, list.Count - 1)].PaintFastSelective(chunk, x2, y2, z, replacevalue);
                    }
                }
            }
        }

        public float CalculateMountainRangeFactor(float x, float z)
        {
            return 1f - MathUtils.Abs(2f * SimplexNoise.OctavedNoise(x, z, 0.0014f, 3, 1.91f, 0.75f) - 1f);
        }

        public void GenerateFCTrees(TerrainChunk chunk)
        {
            Terrain terrain = m_subsystemTerrain.Terrain;
            Point2 origin = chunk.Origin;
            Point2 origin2 = chunk.Origin;
            int x = chunk.Coords.X;
            int y = chunk.Coords.Y;
            for (int i = x; i <= x; i++)
            {
                for (int j = y; j <= y; j++)
                {
                    Random random = new Random(m_seed + i + 3943 * j);
                    int humidity = CalculateHumidity(i * 16, j * 16);
                    int num = CalculateTemperature(i * 16, j * 16);
                    float num2 = MathUtils.Saturate((SimplexNoise.OctavedNoise(i, j, 0.1f, 2, 2f, 0.5f) - 0.25f) / 0.2f + (random.Bool(0.25f) ? 0.5f : 0f));
                    int num3 = (int)(5f * num2);
                    int num4 = 0;
                    for (int k = 0; k < 32; k++)
                    {
                        if (num4 >= num3)
                        {
                            break;
                        }

                        int num5 = i * 16 + random.Int(2, 13);
                        int num6 = j * 16 + random.Int(2, 13);
                        int num7 = terrain.CalculateTopmostCellHeight(num5, num6);
                        if (num7 < 66)
                        {
                            continue;
                        }

                        int cellContentsFast = terrain.GetCellContentsFast(num5, num7, num6);
                        if (cellContentsFast != 2 && cellContentsFast != 8)
                        {
                            continue;
                        }

                        num7++;
                        if (BlocksManager.Blocks[terrain.GetCellContentsFast(num5 + 1, num7, num6)].IsCollidable || BlocksManager.Blocks[terrain.GetCellContentsFast(num5 - 1, num7, num6)].IsCollidable || BlocksManager.Blocks[terrain.GetCellContentsFast(num5, num7, num6 + 1)].IsCollidable || BlocksManager.Blocks[terrain.GetCellContentsFast(num5, num7, num6 - 1)].IsCollidable)
                        {
                            continue;
                        }

                        FCTreeType? fCTreeType = FCPlantManager.GenerateRandomTreeType(random, num + SubsystemWeather.GetTemperatureAdjustmentAtHeight(num7), humidity, num7);
                        if (fCTreeType.HasValue)
                        {
                            if (fCTreeType == FCTreeType.Yinghua)
                            {
                                ReadOnlyList<TerrainBrush> treeBrushes = FCPlantManager.GetTreeBrushes(fCTreeType.Value);
                                TerrainBrush terrainBrush = treeBrushes[random.Int(treeBrushes.Count)];
                                terrainBrush.PaintFast(chunk, num5, num7, num6);
                                chunk.AddBrushPaint(num5, num7, num6, terrainBrush);
                                for (int l = -3; l <= 3; l++)
                                {
                                    for (int m = -3; m <= 3; m++)
                                    {
                                        int x2 = num5 + l;
                                        int y2 = num7;
                                        int z = num6 + m;
                                        if (Terrain.ExtractContents(terrain.GetCellValueFast(x2, y2, z)) == 0 && (l != 0 || m != 0))
                                        {
                                            chunk.SetCellValueFast(x2, y2, z, 963);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                ReadOnlyList<TerrainBrush> treeBrushes2 = FCPlantManager.GetTreeBrushes(fCTreeType.Value);
                                TerrainBrush terrainBrush2 = treeBrushes2[random.Int(treeBrushes2.Count)];
                                terrainBrush2.PaintFast(chunk, num5, num7, num6);
                                chunk.AddBrushPaint(num5, num7, num6, terrainBrush2);
                            }
                        }

                        num4++;
                    }
                }
            }
        }

        public int CalculateTemperature(float x, float z)
        {
            return MathUtils.Clamp((int)(MathUtils.Saturate(3f * SimplexNoise.OctavedNoise(x + m_temperatureOffset.X, z + m_temperatureOffset.Y, 0.0015f / TGBiomeScaling, 5, 2f, 0.6f) - 1.1f + m_worldSettings.TemperatureOffset / 16f) * 16f), 0, 15);
        }

        public int CalculateHumidity(float x, float z)
        {
            return MathUtils.Clamp((int)(MathUtils.Saturate(3f * SimplexNoise.OctavedNoise(x + m_humidityOffset.X, z + m_humidityOffset.Y, 0.0012f / TGBiomeScaling, 5, 2f, 0.6f) - 0.9f + m_worldSettings.HumidityOffset / 16f) * 16f), 0, 15);
        }

        static FCModLoaderShengcheng()
        {
            m_fcmagmaPocketBrushes = new List<TerrainBrush>();
            m_fcmagmaPocketBrushes2 = new List<TerrainBrush>();
            m_fcMoonPocketBrushes = new List<TerrainBrush>();
            m_fccaveBrushesByType = new List<List<TerrainBrush>>();
            listRD = new List<RoadPoint>();
            listBD = new List<BuildPoint>();
            listRDF = new List<RoadPoint>();
            Dic_Chunk_Village3 = new Dictionary<Point2, int>();
            Dic_Chunk_Village_Build = new Dictionary<Point2, TerrainChunk>();
            FCCreateBrushes();
        }

        public void FCGenerateCaves(TerrainChunk chunk)
        {
            if (!TGCavesAndPockets)
            {
                return;
            }

            List<CavePoint> list = new List<CavePoint>();
            int x = chunk.Coords.X;
            int y = chunk.Coords.Y;
            for (int i = x - 3; i <= x + 3; i++)
            {
                for (int j = y - 3; j <= y + 3; j++)
                {
                    list.Clear();
                    Random random = new Random(m_seed + i + 90 * j);
                    int num = i * 16 + random.Int(0, 15);
                    int num2 = j * 16 + random.Int(0, 15);
                    float probability = 1f;
                    if (!random.Bool(probability))
                    {
                        continue;
                    }

                    int num3 = (int)CalculateHeight(num, num2);
                    int num4 = (int)CalculateHeight(num + 3, num2);
                    int num5 = (int)CalculateHeight(num, num2 + 3);
                    Vector3 position = new Vector3(num, num3 - 1, num2);
                    Vector3 v = new Vector3(3f, num4 - num3, 0f);
                    Vector3 v2 = new Vector3(0f, num5 - num3, 3f);
                    Vector3 direction = Vector3.Normalize(Vector3.Cross(v, v2));
                    if (direction.Y > -0.6f)
                    {
                        list.Add(new CavePoint
                        {
                            Position = position,
                            Direction = direction,
                            BrushType = 0,
                            Length = random.Int(80, 240)
                        });
                    }
                    else if (random.Bool(0.04f))
                    {
                        Vector3 position2 = new Vector3(num, random.Float(30f, 54f), num2);
                        list.Add(new CavePoint
                        {
                            Position = position2,
                            Direction = direction,
                            BrushType = 0,
                            Length = random.Int(80, 240)
                        });
                    }
                    else if (random.Bool(0.02f))
                    {
                        list.Add(new CavePoint
                        {
                            Position = position,
                            Direction = direction,
                            BrushType = 0,
                            Length = random.Int(80, 240)
                        });
                    }

                    int num6 = i * 16 + 8;
                    int num7 = j * 16 + 8;
                    int num8 = 0;
                    while (num8 < list.Count)
                    {
                        CavePoint cavePoint = list[num8];
                        List<TerrainBrush> list2 = m_fccaveBrushesByType[cavePoint.BrushType];
                        list2[random.Int(0, list2.Count - 1)].PaintFastAvoidWater(chunk, Terrain.ToCell(cavePoint.Position.X), Terrain.ToCell(cavePoint.Position.Y), Terrain.ToCell(cavePoint.Position.Z));
                        cavePoint.Position += 2f * cavePoint.Direction;
                        cavePoint.StepsTaken += 2;
                        float num9 = cavePoint.Position.X - (float)num6;
                        float num10 = cavePoint.Position.Z - (float)num7;
                        if (random.Bool(0.5f))
                        {
                            Vector3 vector = Vector3.Normalize(random.Vector3(1f));
                            if ((num9 < -25.5f && vector.X < 0f) || (num9 > 25.5f && vector.X > 0f))
                            {
                                vector.X = 0f - vector.X;
                            }

                            if ((num10 < -25.5f && vector.Z < 0f) || (num10 > 25.5f && vector.Z > 0f))
                            {
                                vector.Z = 0f - vector.Z;
                            }

                            if ((cavePoint.Direction.Y < -0.5f && vector.Y < -10f) || (cavePoint.Direction.Y > 0.1f && vector.Y > 0f))
                            {
                                vector.Y = 0f - vector.Y;
                            }

                            cavePoint.Direction = Vector3.Normalize(cavePoint.Direction + 0.5f * vector);
                        }

                        if (cavePoint.StepsTaken > 20 && random.Bool(0.06f))
                        {
                            cavePoint.Direction = Vector3.Normalize(random.Vector3(1f) * new Vector3(1f, 0.33f, 1f));
                        }

                        if (cavePoint.StepsTaken > 20 && random.Bool(0.05f))
                        {
                            cavePoint.Direction.Y = 0f;
                            cavePoint.BrushType = MathUtils.Min(cavePoint.BrushType + 2, m_fccaveBrushesByType.Count - 1);
                        }

                        if (cavePoint.StepsTaken > 30 && random.Bool(0.03f))
                        {
                            cavePoint.Direction.X = 0f;
                            cavePoint.Direction.Y = -1f;
                            cavePoint.Direction.Z = 0f;
                        }

                        if (cavePoint.StepsTaken > 30 && cavePoint.Position.Y < 30f && random.Bool(0.02f))
                        {
                            cavePoint.Direction.X = 0f;
                            cavePoint.Direction.Y = 1f;
                            cavePoint.Direction.Z = 0f;
                        }

                        if (random.Bool(0.33f))
                        {
                            cavePoint.BrushType = (int)(MathUtils.Pow(random.Float(0f, 0.999f), 7f) * (float)m_fccaveBrushesByType.Count);
                        }

                        if (random.Bool(0.06f) && list.Count < 12 && cavePoint.StepsTaken > 20 && cavePoint.Position.Y < 58f)
                        {
                            list.Add(new CavePoint
                            {
                                Position = cavePoint.Position,
                                Direction = Vector3.Normalize(random.Vector3(1f, 1f) * new Vector3(1f, 0.33f, 1f)),
                                BrushType = (int)(MathUtils.Pow(random.Float(0f, 0.999f), 7f) * (float)m_fccaveBrushesByType.Count),
                                Length = random.Int(40, 180)
                            });
                        }

                        if (cavePoint.StepsTaken >= cavePoint.Length || MathUtils.Abs(num9) > 100f || MathUtils.Abs(num10) > 100f || cavePoint.Position.Y < 10f || cavePoint.Position.Y > 246f)
                        {
                            num8++;
                        }
                        else if (cavePoint.StepsTaken % 20 == 0)
                        {
                            float num11 = CalculateHeight(cavePoint.Position.X, cavePoint.Position.Z);
                            if (cavePoint.Position.Y > num11 + 1f)
                            {
                                num8++;
                            }
                        }
                    }
                }
            }
        }

        public float CalculateHeight(float x, float z)
        {
            float num = TGOceanSlope + TGOceanSlopeVariation * MathUtils.PowSign(2f * SimplexNoise.OctavedNoise(x + m_mountainsOffset.X, z + m_mountainsOffset.Y, 0.01f, 1, 2f, 0.5f) - 1f, 0.5f);
            float num2 = CalculateOceanShoreDistance(x, z);
            float num3 = MathUtils.Saturate(2f - 0.05f * MathUtils.Abs(num2));
            float num4 = MathUtils.Saturate(MathUtils.Sin(TGIslandsFrequency * num2));
            float num5 = MathUtils.Saturate(MathUtils.Saturate((0f - num) * num2) - 0.85f * num4);
            float num6 = MathUtils.Saturate(MathUtils.Saturate(0.05f * (0f - num2 - 10f)) - num4);
            float v = CalculateMountainRangeFactor(x, z);
            float f = (1f - num3) * SimplexNoise.OctavedNoise(x, z, 0.001f / TGBiomeScaling, 2, 2f, 0.5f);
            float f2 = (1f - num3) * SimplexNoise.OctavedNoise(x, z, 0.0017f / TGBiomeScaling, 2, 4f, 0.7f);
            float num7 = (1f - num6) * (1f - num3) * TerrainContentsGenerator23.Squish(v, 1f - TGHillsPercentage, 1f - TGMountainsPercentage);
            float num8 = (1f - num6) * TerrainContentsGenerator23.Squish(v, 1f - TGMountainsPercentage, 1f);
            float num9 = 1f * SimplexNoise.OctavedNoise(x, z, TGHillsFrequency, TGHillsOctaves, 1.93f, TGHillsPersistence);
            float amplitudeStep = MathUtils.Lerp(0.75f * TerrainContentsGenerator23.TGMountainsDetailPersistence, 1.33f * TerrainContentsGenerator23.TGMountainsDetailPersistence, f);
            float num10 = 1.5f * SimplexNoise.OctavedNoise(x, z, TerrainContentsGenerator23.TGMountainsDetailFreq, TerrainContentsGenerator23.TGMountainsDetailOctaves, 1.98f, amplitudeStep) - 0.5f;
            float num11 = MathUtils.Lerp(60f, 30f, MathUtils.Saturate(1f * num8 + 0.5f * num7 + MathUtils.Saturate(1f - num2 / 30f)));
            float x2 = MathUtils.Lerp(-2f, -4f, MathUtils.Saturate(num8 + 0.5f * num7));
            float num12 = MathUtils.Saturate(1.5f - num11 * MathUtils.Abs(2f * SimplexNoise.OctavedNoise(x + m_riversOffset.X, z + m_riversOffset.Y, 0.001f, 4, 2f, 0.5f) - 1f));
            float num13 = -50f * num5 + TGHeightBias;
            float num14 = MathUtils.Lerp(0f, 8f, f);
            float num15 = MathUtils.Lerp(0f, -6f, f2);
            float num16 = TGHillsStrength * num7 * num9;
            float num17 = TGMountainsStrength * num8 * num10;
            float f3 = TGRiversStrength * num12;
            float num18 = num13 + num14 + num15 + num17 + num16;
            float num19 = MathUtils.Min(MathUtils.Lerp(num18, x2, f3), num18);
            return MathUtils.Clamp(64f + num19, 10f, 251f);
        }

        public float CalculateOceanShoreDistance(float x, float z)
        {
            if (m_islandSize.HasValue)
            {
                float num = CalculateOceanShoreX(z);
                float num2 = CalculateOceanShoreZ(x);
                float num3 = CalculateOceanShoreX(z + 1000f) + m_islandSize.Value.X;
                float num4 = CalculateOceanShoreZ(x + 1000f) + m_islandSize.Value.Y;
                return MathUtils.Min(x - num, z - num2, num3 - x, num4 - z);
            }

            float num5 = CalculateOceanShoreX(z);
            float num6 = CalculateOceanShoreZ(x);
            return MathUtils.Min(x - num5, z - num6);
        }

        public float CalculateOceanShoreX(float z)
        {
            return m_oceanCorner.X + TGShoreFluctuations * SimplexNoise.OctavedNoise(z, 0f, 0.005f / TGShoreFluctuationsScaling, 4, 1.95f, 1f);
        }

        public float CalculateOceanShoreZ(float x)
        {
            return m_oceanCorner.Y + TGShoreFluctuations * SimplexNoise.OctavedNoise(0f, x, 0.005f / TGShoreFluctuationsScaling, 4, 1.95f, 1f);
        }

        public void GenerateFCPockets(TerrainChunk chunk)
        {
            if (!TGCavesAndPockets)
            {
                return;
            }

            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    int num = i + chunk.Coords.X;
                    int num2 = j + chunk.Coords.Y;
                    Random random = new Random(m_seed + num + 71 * num2);
                    int num3 = random.Int(0, 10);
                    for (int k = 0; k < num3; k++)
                    {
                        random.Int(0, 1);
                    }

                    float num4 = CalculateMountainRangeFactor(num * 16, num2 * 16);
                    if (random.Bool(0.06f + 0.05f * num4))
                    {
                        int num5 = num * 16;
                        int num6 = random.Int(35, 42);
                        int num7 = num2 * 16;
                        int num8 = random.Int(1, 2);
                        for (int l = 0; l < num8; l++)
                        {
                            Vector2 vector = random.Vector2(7f);
                            int num9 = 8 + (int)MathUtils.Round(vector.X);
                            int num10 = random.Int(0, 1);
                            int num11 = 8 + (int)MathUtils.Round(vector.Y);
                            m_fcmagmaPocketBrushes[random.Int(0, m_fcmagmaPocketBrushes.Count - 1)].PaintFast(chunk, num5 + num9, num6 + num10, num7 + num11);
                        }
                    }
                }
            }
        }

        public static void FCCreateBrushes()
        {
            Random random = new Random(17);
            int[] array = new int[4] { 8, 12, 14, 16 };
            for (int i = 0; i < 4 * array.Length; i++)
            {
                TerrainBrush terrainBrush = new TerrainBrush();
                int num = array[i / 4];
                int num2 = num + 2;
                float num3 = ((i % 4 == 2) ? 0.5f : 1f);
                int num4 = ((i % 4 == 1) ? (num * num) : (2 * num * num));
                for (int j = 0; j < num4; j++)
                {
                    Vector2 vector = random.Vector2(0f, num);
                    float num5 = vector.Length();
                    int num6 = random.Int(3, 4);
                    int sizeY = 1 + (int)MathUtils.Lerp(MathUtils.Max(num / 3, 2.5f) * num3, 0f, num5 / (float)num) + random.Int(0, 1);
                    int num7 = 1 + (int)MathUtils.Lerp(num2, 0f, num5 / (float)num) + random.Int(0, 1);
                    terrainBrush.AddBox((int)MathUtils.Floor(vector.X), 0, (int)MathUtils.Floor(vector.Y), num6, sizeY, num6, 0);
                    terrainBrush.AddBox((int)MathUtils.Floor(vector.X), -num7, (int)MathUtils.Floor(vector.Y), num6, num7, num6, 0);
                }

                terrainBrush.Compile();
                m_fcmagmaPocketBrushes2.Add(terrainBrush);
            }

            NumberWeightPair[] array2 = new NumberWeightPair[7]
            {
                new NumberWeightPair(16, 8),
                new NumberWeightPair(0, 80),
                new NumberWeightPair(41, 3),
                new NumberWeightPair(39, 3),
                new NumberWeightPair(101, 1),
                new NumberWeightPair(112, 1),
                new NumberWeightPair(934, 4)
            };
            int num8 = 0;
            NumberWeightPair[] array3 = array2;
            for (int k = 0; k < array3.Length; k++)
            {
                NumberWeightPair numberWeightPair = array3[k];
                num8 += numberWeightPair.weight;
            }

            int num9 = random.Int(0, num8 - 1);
            int[] array4 = new int[4] { 16, 24, 28, 30 };
            for (int l = 0; l < 4 * array4.Length; l++)
            {
                TerrainBrush terrainBrush2 = new TerrainBrush();
                int num10 = array4[l / 4];
                int num11 = num10 + 2;
                float num12 = ((l % 4 == 2) ? 0.5f : 1f);
                int num13 = ((l % 4 == 1) ? (num10 * num10) : (2 * num10 * num10));
                for (int m = 0; m < num13; m++)
                {
                    Vector2 vector2 = random.Vector2(0f, num10);
                    float num14 = vector2.Length();
                    int num15 = random.Int(3, 4);
                    int sizeY2 = 1 + (int)MathUtils.Lerp(MathUtils.Max(num10 / 3, 2.5f) * num12, 0f, num14 / (float)num10) + random.Int(0, 1);
                    int num16 = 1 + (int)MathUtils.Lerp(num11, 0f, num14 / (float)num10) + random.Int(0, 1);
                    int num17 = -1;
                    int num19 = 0;
                    NumberWeightPair[] array5 = array2;
                    for (int n = 0; n < array5.Length; n++)
                    {
                        NumberWeightPair numberWeightPair2 = array5[n];
                        num19 += numberWeightPair2.weight;
                        if (num9 < num19)
                        {
                            num17 = numberWeightPair2.number;
                            break;
                        }
                    }

                    if (num17 == 0)
                    {
                    }

                    if (num16 - 15 > 0)
                    {
                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 16;
                        }

                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 39;
                        }

                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 112;
                        }

                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 41;
                        }

                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 101;
                        }

                        if (random.Bool(0.0001f) && num17 == 0)
                        {
                            num17 = 148;
                        }
                    }

                    terrainBrush2.AddBox((int)MathUtils.Floor(vector2.X), 0, (int)MathUtils.Floor(vector2.Y), num15, sizeY2, num15, 0);
                    if (num17 != 0)
                    {
                        if (random.Bool(0.1f))
                        {
                            terrainBrush2.AddBox((int)MathUtils.Floor(vector2.X), -num16, (int)MathUtils.Floor(vector2.Y), num15, num16, num15, num17);
                        }
                    }
                    else if (num17 == 0)
                    {
                        terrainBrush2.AddBox((int)MathUtils.Floor(vector2.X), -num16, (int)MathUtils.Floor(vector2.Y), num15, num16, num15, num17);
                    }
                }

                terrainBrush2.Compile();
                m_fcmagmaPocketBrushes.Add(terrainBrush2);
            }

            NumberWeightPair[] array6 = new NumberWeightPair[7]
            {
                new NumberWeightPair(16, 8),
                new NumberWeightPair(0, 80),
                new NumberWeightPair(41, 3),
                new NumberWeightPair(39, 3),
                new NumberWeightPair(101, 1),
                new NumberWeightPair(112, 1),
                new NumberWeightPair(934, 4)
            };
            int num20 = 0;
            NumberWeightPair[] array7 = array2;
            for (int num21 = 0; num21 < array7.Length; num21++)
            {
                NumberWeightPair numberWeightPair3 = array7[num21];
                num20 += numberWeightPair3.weight;
            }

            int num22 = random.Int(0, num20 - 1);
            int[] array8 = new int[4] { 8, 24, 28, 30 };
            for (int num23 = 0; num23 < 4 * array8.Length; num23++)
            {
                TerrainBrush terrainBrush3 = new TerrainBrush();
                int num24 = array4[num23 / 4];
                int num25 = num24 + 2;
                float num26 = ((num23 % 4 == 2) ? 0.5f : 1f);
                int num27 = ((num23 % 4 == 1) ? (num24 * num24) : (2 * num24 * num24));
                for (int num28 = 0; num28 < num27; num28++)
                {
                    Vector2 vector3 = random.Vector2(0f, num24);
                    float num29 = vector3.Length();
                    int num30 = random.Int(3, 4);
                    int sizeY3 = 1 + (int)MathUtils.Lerp(MathUtils.Max(num24 / 3, 2.5f) * num26, 0f, num29 / (float)num24) + random.Int(0, 1);
                    int num31 = 1 + (int)MathUtils.Lerp(num25, 0f, num29 / (float)num24) + random.Int(0, 1);
                    int num32 = -1;
                    int num33 = 0;
                    int num34 = 0;
                    NumberWeightPair[] array9 = array6;
                    for (int num35 = 0; num35 < array9.Length; num35++)
                    {
                        NumberWeightPair numberWeightPair4 = array9[num35];
                        num34 += numberWeightPair4.weight;
                        if (num22 < num34)
                        {
                            num32 = numberWeightPair4.number;
                            break;
                        }
                    }

                    if (num32 == 0)
                    {
                        num33 = 980;
                    }

                    if (num31 - 15 > 0)
                    {
                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 16;
                        }

                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 39;
                        }

                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 112;
                        }

                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 41;
                        }

                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 101;
                        }

                        if (random.Bool(0.0001f) && num32 == 0)
                        {
                            num32 = 148;
                        }
                    }

                    terrainBrush3.AddBox((int)MathUtils.Floor(vector3.X), 0, (int)MathUtils.Floor(vector3.Y), num30, sizeY3, num30, 0);
                    if (num32 != 0)
                    {
                        if (random.Bool(0.1f))
                        {
                            terrainBrush3.AddBox((int)MathUtils.Floor(vector3.X), -num31, (int)MathUtils.Floor(vector3.Y), num30, num31, num30, num32);
                        }
                    }
                    else if (num32 == 0)
                    {
                        terrainBrush3.AddBox((int)MathUtils.Floor(vector3.X), -num31, (int)MathUtils.Floor(vector3.Y), num30, num31, num30, num32);
                    }
                }

                terrainBrush3.Compile();
                m_fcMoonPocketBrushes.Add(terrainBrush3);
            }

            for (int num36 = 0; num36 < 7; num36++)
            {
                m_fccaveBrushesByType.Add(new List<TerrainBrush>());
                for (int num37 = 0; num37 < 3; num37++)
                {
                    TerrainBrush terrainBrush4 = new TerrainBrush();
                    int num38 = 6 + 4 * num36;
                    int max = 7 + num36 / 3;
                    int max2 = 12 + num36;
                    for (int num39 = 0; num39 < num38; num39++)
                    {
                        int num40 = random.Int(2, max);
                        int num41 = random.Int(11, max2) - num40;
                        Vector3 vector4 = 0.5f * new Vector3(random.Float(-1f, 1f), random.Float(0f, 1f), random.Float(-1f, 1f));
                        Vector3 zero = Vector3.Zero;
                        for (int num42 = 0; num42 < num41; num42++)
                        {
                            terrainBrush4.AddBox((int)MathUtils.Floor(zero.X) - num40 / 2, (int)MathUtils.Floor(zero.Y) - num40 / 2, (int)MathUtils.Floor(zero.Z) - num40 / 2, num40, num40, num40, 0);
                            zero += vector4;
                        }
                    }

                    terrainBrush4.Compile();
                    m_fccaveBrushesByType[num36].Add(terrainBrush4);
                }
            }
        }

        public void FCGenerateTerrain(TerrainChunk chunk, int x1, int z1, int x2, int z2)
        {
            int num = x2 - x1;
            int num2 = z2 - z1;
            Terrain terrain = m_subsystemTerrain.Terrain;
            int num3 = chunk.Origin.X + x1;
            int num4 = chunk.Origin.Y + z1;
            TerrainContentsGenerator23.Grid2d grid2d = new TerrainContentsGenerator23.Grid2d(num, num2);
            TerrainContentsGenerator23.Grid2d grid2d2 = new TerrainContentsGenerator23.Grid2d(num, num2);
            for (int i = 0; i < num2; i++)
            {
                for (int j = 0; j < num; j++)
                {
                    grid2d.Set(j, i, CalculateOceanShoreDistance(j + num3, i + num4));
                    grid2d2.Set(j, i, CalculateMountainRangeFactor(j + num3, i + num4));
                }
            }

            TerrainContentsGenerator23.Grid3d grid3d = new TerrainContentsGenerator23.Grid3d(num / 4 + 1, 33, num2 / 4 + 1);
            for (int k = 0; k < grid3d.SizeX; k++)
            {
                for (int l = 0; l < grid3d.SizeZ; l++)
                {
                    int num5 = k * 4 + num3;
                    int num6 = l * 4 + num4;
                    float num7 = CalculateHeight(num5, num6);
                    float v = CalculateMountainRangeFactor(num5, num6);
                    float num8 = MathUtils.Lerp(TGMinTurbulence, 1f, TerrainContentsGenerator23.Squish(v, TGTurbulenceZero, 1f));
                    for (int m = 0; m < grid3d.SizeY; m++)
                    {
                        int num9 = m * 8;
                        float num10 = TGTurbulenceStrength * num8 * MathUtils.Saturate(num7 - (float)num9) * (2f * SimplexNoise.OctavedNoise(num5, num9, num6, TGTurbulenceFreq, TGTurbulenceOctaves, 4f, TGTurbulencePersistence) - 1f);
                        float num11 = (float)num9 + num10;
                        float num12 = num7 - num11;
                        num12 += MathUtils.Max(4f * (TGDensityBias - (float)num9), 0f);
                        grid3d.Set(k, m, l, num12);
                    }
                }
            }

            SubsystemTerrain subsystemTerrain = new SubsystemTerrain();
            TerrainContentsGenerator23 terrainContentsGenerator = new TerrainContentsGenerator23(subsystemTerrain);
            int oceanLevel = terrainContentsGenerator.OceanLevel;
            for (int n = 0; n < grid3d.SizeX - 1; n++)
            {
                for (int num13 = 0; num13 < grid3d.SizeZ - 1; num13++)
                {
                    for (int num14 = 0; num14 < grid3d.SizeY - 1; num14++)
                    {
                        grid3d.Get8(n, num14, num13, out var v2, out var v3, out var v4, out var v5, out var v6, out var v7, out var v8, out var v9);
                        float num15 = (v3 - v2) / 4f;
                        float num16 = (v5 - v4) / 4f;
                        float num17 = (v7 - v6) / 4f;
                        float num18 = (v9 - v8) / 4f;
                        float num19 = v2;
                        float num20 = v4;
                        float num21 = v6;
                        float num22 = v8;
                        for (int num23 = 0; num23 < 4; num23++)
                        {
                            float num24 = (num21 - num19) / 4f;
                            float num25 = (num22 - num20) / 4f;
                            float num26 = num19;
                            float num27 = num20;
                            for (int num28 = 0; num28 < 4; num28++)
                            {
                                float num29 = (num27 - num26) / 8f;
                                float num30 = num26;
                                int num31 = num23 + n * 4;
                                int num32 = num28 + num13 * 4;
                                int x3 = x1 + num31;
                                int z3 = z1 + num32;
                                float x4 = grid2d.Get(num31, num32);
                                float num33 = grid2d2.Get(num31, num32);
                                int temperatureFast = chunk.GetTemperatureFast(x3, z3);
                                int humidityFast = chunk.GetHumidityFast(x3, z3);
                                float f = num33 - 0.01f * (float)humidityFast;
                                float num34 = MathUtils.Lerp(100f, 0f, f);
                                float num35 = MathUtils.Lerp(300f, 30f, f);
                                bool flag = (temperatureFast > 8 && humidityFast < 8 && num33 < 0.97f) || (MathUtils.Abs(x4) < 16f && num33 < 0.97f);
                                int num36 = TerrainChunk.CalculateCellIndex(x3, 0, z3);
                                for (int num37 = 0; num37 < 8; num37++)
                                {
                                    int num38 = num37 + num14 * 8;
                                    int value = 0;
                                    if (num30 < 0f)
                                    {
                                        if (num38 <= oceanLevel)
                                        {
                                            value = 18;
                                        }
                                    }
                                    else
                                    {
                                        value = (flag ? ((!(num30 >= num34)) ? 4 : ((num30 >= num35) ? 67 : 3)) : ((num30 >= num35) ? 67 : 3));
                                    }

                                    chunk.SetCellValueFast(num36 + num38, value);
                                    num30 += num29;
                                }

                                num26 += num24;
                                num27 += num25;
                            }

                            num19 += num15;
                            num20 += num16;
                            num21 += num17;
                            num22 += num18;
                        }
                    }
                }
            }
        }

        public void FCGenerateSurface(TerrainChunk chunk)
        {
            ComponentPlayer componentPlayer = new ComponentPlayer();
            bool flag = true;
            bool flag2 = true;
            bool flag3 = true;
            int x = chunk.Origin.X;
            int y = chunk.Origin.Y;
            int x2 = chunk.Coords.X;
            int y2 = chunk.Coords.Y;
            int x3 = x + 8;
            int z = y + 8;
            Vector3 vector = m_subsystemTerrain.TerrainContentsGenerator.FindCoarseSpawnPosition();
            Point2 point = ((int)vector.X, (int)vector.Z);
            Point2 point2 = (x2, y2);
            Terrain terrain = m_subsystemTerrain.Terrain;
            int num = terrain.CalculateTopmostCellHeight(x3, z);
            Random random = new Random(m_seed + chunk.Coords.X + 101 * chunk.Coords.Y);
            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    int num2 = i + chunk.Origin.X;
                    int num3 = j + chunk.Origin.Y;
                    int num4 = TerrainChunk.CalculateCellIndex(i, 254, j);
                    int num5 = 254;
                    while (num5 >= 64)
                    {
                        int cellValueFast = chunk.GetCellValueFast(num4);
                        int num6 = Terrain.ExtractContents(cellValueFast);
                        if (!BlocksManager.Blocks[num6].IsTransparent_(cellValueFast))
                        {
                            float num7 = CalculateMountainRangeFactor(num2, num3);
                            int temperature = terrain.GetTemperature(num2, num3);
                            int humidity = terrain.GetHumidity(num2, num3);
                            int num8 = 8;
                            int num9 = ((num5 + 1 < 255) ? chunk.GetCellContentsFast(i, num5 + 1, j) : 0);
                            int num10 = ((num5 + 1 < 255) ? chunk.GetCellContentsFast(i, num5 - 1, j) : 0);
                            if (num6 != 8)
                            {
                                return;
                            }

                            if (num9 != 233 && num9 != 232 && num9 != 18 && num10 == 2 && humidity >= 5 && temperature >= 3 && temperature <= 10)
                            {
                                num8 = 984;
                            }
                            else if (num9 != 233 && num9 != 232 && num9 != 18 && num10 == 2 && humidity >= 7 && temperature >= 8)
                            {
                                num8 = 985;
                            }

                            if (num8 != 8 && flag)
                            {
                                if (num8 == 984 && flag2)
                                {
                                    for (int k = x2; k <= x2; k++)
                                    {
                                        for (int l = y2; l <= y2; l++)
                                        {
                                            float num11 = MathUtils.Saturate((SimplexNoise.OctavedNoise(k, l, 0.1f, 2, 2f, 0.5f) - 0.25f) / 0.2f + (random.Bool(0.25f) ? 0.5f : 0f));
                                            int num12 = (int)(5f * num11);
                                            int num13 = 0;
                                            for (int m = 0; m < 20; m++)
                                            {
                                                if (num13 >= num12)
                                                {
                                                    break;
                                                }

                                                int num14 = k * 16 + random.Int(2, 13);
                                                int num15 = l * 16 + random.Int(2, 13);
                                                int num16 = terrain.CalculateTopmostCellHeight(num14, num15);
                                                if (num16 < 66)
                                                {
                                                    continue;
                                                }

                                                int cellContentsFast = terrain.GetCellContentsFast(num14, num16, num15);
                                                if (cellContentsFast == 2 || cellContentsFast == 8 || cellContentsFast == 984)
                                                {
                                                    num16++;
                                                    if (!BlocksManager.Blocks[terrain.GetCellContentsFast(num14 + 1, num16, num15)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num14 - 1, num16, num15)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num14, num16, num15 + 1)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num14, num16, num15 - 1)].IsCollidable)
                                                    {
                                                        ReadOnlyList<TerrainBrush> treeBrushes = FCPlantManager.GetTreeBrushes(FCTreeType.Yinghua);
                                                        TerrainBrush terrainBrush = treeBrushes[random.Int(treeBrushes.Count)];
                                                        terrainBrush.PaintFast(chunk, num14, num16, num15);
                                                        chunk.AddBrushPaint(num14, num16, num15, terrainBrush);
                                                        num13++;
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    flag2 = false;
                                }

                                if (num8 != 985 || !flag3)
                                {
                                    break;
                                }

                                for (int n = x2; n <= x2; n++)
                                {
                                    for (int num17 = y2; num17 <= y2; num17++)
                                    {
                                        float num18 = MathUtils.Saturate((SimplexNoise.OctavedNoise(n, num17, 0.1f, 2, 2f, 0.5f) - 0.25f) / 0.2f + (random.Bool(0.25f) ? 0.5f : 0f));
                                        int num19 = (int)(5f * num18);
                                        int num20 = 0;
                                        for (int num21 = 0; num21 < 10; num21++)
                                        {
                                            if (num20 >= num19)
                                            {
                                                break;
                                            }

                                            int num22 = n * 16 + random.Int(2, 13);
                                            int num23 = num17 * 16 + random.Int(2, 13);
                                            int num24 = terrain.CalculateTopmostCellHeight(num22, num23);
                                            FCTreeType[] array = new FCTreeType[3]
                                            {
                                                FCTreeType.Apple,
                                                FCTreeType.Orange,
                                                FCTreeType.Coco
                                            };
                                            FCTreeType treeType = array[random.Int(array.Length)];
                                            int cellContentsFast2 = terrain.GetCellContentsFast(num22, num24, num23);
                                            if (cellContentsFast2 != 2 && cellContentsFast2 != 8 && cellContentsFast2 != 984)
                                            {
                                                continue;
                                            }

                                            num24++;
                                            if (!BlocksManager.Blocks[terrain.GetCellContentsFast(num22 + 1, num24, num23)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num22 - 1, num24, num23)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num22, num24, num23 + 1)].IsCollidable && !BlocksManager.Blocks[terrain.GetCellContentsFast(num22, num24, num23 - 1)].IsCollidable)
                                            {
                                                if (random.Bool(0.1f))
                                                {
                                                    treeType = FCTreeType.Lorejun;
                                                }

                                                ReadOnlyList<TerrainBrush> treeBrushes2 = FCPlantManager.GetTreeBrushes(treeType);
                                                TerrainBrush terrainBrush2 = treeBrushes2[random.Int(treeBrushes2.Count)];
                                                terrainBrush2.PaintFast(chunk, num22, num24, num23);
                                                chunk.AddBrushPaint(num23, num24, num23, terrainBrush2);
                                                num20++;
                                            }
                                        }
                                    }
                                }

                                flag3 = false;
                                break;
                            }
                        }

                        num5--;
                        num4--;
                    }
                }
            }
        }
    }
}